1   /*                        __    __  __  __    __  ___
2    *                       \  \  /  /    \  \  /  /  __/
3    *                        \  \/  /  /\  \  \/  /  /
4    *                         \____/__/  \__\____/__/.ɪᴏ
5    * ᶜᵒᵖʸʳᶦᵍʰᵗ ᵇʸ ᵛᵃᵛʳ ⁻ ˡᶦᶜᵉⁿˢᵉᵈ ᵘⁿᵈᵉʳ ᵗʰᵉ ᵃᵖᵃᶜʰᵉ ˡᶦᶜᵉⁿˢᵉ ᵛᵉʳˢᶦᵒⁿ ᵗʷᵒ ᵈᵒᵗ ᶻᵉʳᵒ
6    */
7   package io.vavr.collection.euler;
8   
9   import io.vavr.API;
10  import io.vavr.Function1;
11  import io.vavr.collection.Iterator;
12  import io.vavr.collection.Stream;
13  
14  import java.io.File;
15  import java.io.FileNotFoundException;
16  import java.math.BigInteger;
17  import java.net.URL;
18  import java.util.Scanner;
19  
20  import static io.vavr.API.$;
21  import static io.vavr.API.Case;
22  
23  final class Utils {
24  
25      private Utils() {
26      }
27  
28      static final Function1<Integer, BigInteger> MEMOIZED_FACTORIAL = Function1.of(Utils::factorial).memoized();
29  
30      static final Function1<Long, Boolean> MEMOIZED_IS_PRIME = Function1.of(Utils::isPrime).memoized();
31  
32      static Stream<BigInteger> fibonacci() {
33          return Stream.of(BigInteger.ZERO, BigInteger.ONE).appendSelf(self -> self.zip(self.tail()).map(t -> t._1.add(t._2)));
34      }
35  
36      static BigInteger factorial(int n) {
37          return Stream.rangeClosed(1, n).map(BigInteger::valueOf).fold(BigInteger.ONE, BigInteger::multiply);
38      }
39  
40      static Stream<Long> factors(long number) {
41          return Stream.rangeClosed(1, (long) Math.sqrt(number))
42                  .filter(d -> number % d == 0)
43                  .flatMap(d -> Stream.of(d, number / d))
44                  .distinct();
45      }
46  
47      static Stream<Long> divisors(long l) {
48          return factors(l).filter((d) -> d < l);
49      }
50  
51      static boolean isPrime(long val) {
52          return API.Match(val).of(
53                  API.Case($(n -> n < 2L), false),
54                  API.Case($(2L), true),
55                  API.Case($(), n -> {
56                      final double upperLimitToCheck = Math.sqrt(n);
57                      return !PrimeNumbers.primes().takeWhile(d -> d <= upperLimitToCheck).exists(d -> n % d == 0);
58                  })
59          );
60      }
61  
62      static Stream<String> readLines(File file) {
63          try {
64              return Stream.ofAll(new Iterator<String>() {
65  
66                  final Scanner scanner = new Scanner(file);
67  
68                  @Override
69                  public boolean hasNext() {
70                      final boolean hasNext = scanner.hasNextLine();
71                      if (!hasNext) {
72                          scanner.close();
73                      }
74                      return hasNext;
75                  }
76  
77                  @Override
78                  public String next() {
79                      return scanner.nextLine();
80                  }
81              });
82          } catch (FileNotFoundException e) {
83              return Stream.empty();
84          }
85      }
86  
87      static File file(String fileName) {
88          final URL resource = Utils.class.getResource(fileName);
89          if (resource == null) {
90              throw new RuntimeException("resource not found");
91          }
92          return new File(resource.getFile());
93      }
94  
95      static String reverse(String s) {
96          return new StringBuilder(s).reverse().toString();
97      }
98  
99      static boolean isPalindrome(String val) {
100         return val.equals(reverse(val));
101     }
102 
103     static boolean isPalindrome(int val) {
104         return isPalindrome(Long.toString(val));
105     }
106 }